/*************************************************************************
	> File Name: server.c
	> Author: 
	> Mail: 
	> Created Time: Fri 13 Jan 2017 08:36:59 PM PST
 ************************************************************************/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <wait.h>
#include <sys/select.h>
#include <sqlite3.h>
#include "student.h"

#define BACK 1024
USER fir;
USER *msg = &fir;
INFO info;
static int t;

void do_clean()
{
    int nrow,ncolumn;
    char buf[100] = {0};
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    sprintf(buf,"update passwod set flag='0';");
    char **resultp = NULL;
    if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
    {
        fprintf(stderr, "clean--sqlite3 get table: %s\n", errmsg);
        exit(-1);
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    return;
}

void handler(int sigo)
{
    while(waitpid(-1,NULL,WNOHANG) > 0);
}
void do_register(int connfd)
{
    int ret;
    int nrow = 1,ncolumn;
    char buf[100] = {0};
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    char **resultp = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    while(1)
    {
        bzero(buf,sizeof(buf));
        if(nrow == 0){
            ret = recv(connfd,msg,sizeof(*msg),0);
            if(ret < 0){
                perror("msg.du");
                break;
            }
        }
        msg->name[strlen(msg->name)-1] = '\0';
        while(msg->name[strlen(msg->name)-1] ==' '){
            msg->name[strlen(msg->name)-1] = '\0';
        }
        msg->pwd[strlen(msg->pwd)-1] = '\0';
        while(msg->pwd[strlen(msg->pwd)-1] ==' '){
            msg->pwd[strlen(msg->pwd)-1] = '\0';
        }
        sprintf(buf,"select * from passwod where user ='%s'and pwd ='%s' and flag='0';",msg->name,msg->pwd);
        if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
        {
            fprintf(stderr, "du--sqlite3 get table: %s\n", errmsg);
            break;
        }else if(nrow > 0){
            send(connfd,"C",2,0);
            break;
        }
        else if(nrow == 0){
            send(connfd,"N",2,0);
            continue;
        }
    }
    bzero(buf,sizeof(buf));
    sprintf(buf,"update passwod set flag='1' where user='%s';",msg->name);
    if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
    {
        fprintf(stderr, "du--sqlite3 get table: %s\n", errmsg);
        exit(-1);
    }
    if(strncmp(msg->name,"administrator",13) == 0){
        t = 1;
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    return;
}

int  do_adminfind(int connfd)
{
    if(strncmp(msg->name,"administrator",13) != 0){
        return -1;
    }
    int ret;
    int nrow,ncolumn;
    char buf[100] = {0};
    char buff[20] = {0};
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    char **resultp = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    bzero(buf,sizeof(buf));
    sprintf(buf,"select * from informan;");
    if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg))
    {
        fprintf(stderr, "adminfind--sqlite3 get table: %s\n", errmsg);
        exit(-1);
    }
    printf("%s\n",buf);
    if(nrow == 0){
        send(connfd,"N",2,0);
        return 0;
    }
    if(nrow > 0)
    {
        send(connfd,"Y",2,0);
        int i, j;
        int count = 0;
        for (i = 0; i < nrow+1; i++) 
        {
            bzero(buff,sizeof(buff));
            for(j = 0;j < ncolumn;j++)
            {
                if(i == 0 && j < ncolumn)
                {
                    count++;
                    continue;  
                }
                sprintf(buff,"%-5s\n",resultp[count++]);
                ret = send(connfd,buff,sizeof(buff),0);
            }
        }
        bzero(buf,sizeof(buff));
        sprintf(buff,"over");
        send(connfd,buff,strlen(buff),0);
    }
    if(0 != sqlite3_close(db)){
        fprintf(stderr,"sqlite3_close: %s\n",sqlite3_errmsg(db));
        exit(-1);
    }
    return 0;
}
void do_find(int connfd)
{
    int ret;
    char buf[300] = {0};
    if(t == 1){
        if(do_adminfind(connfd) < 0){
            send(connfd,"N",2,0);
        }
        return;
        printf("lin",__LINE__);
    }
    int nrow,ncolumn;
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    char **resultp = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    msg->name[strlen(msg->name)-1] = '\0';
    while(msg->name[strlen(msg->name)-1] ==' '){
        msg->name[strlen(msg->name)-1] = '\0';
    }
    bzero(buf,sizeof(buf));
    sprintf(buf,"select * from informan where name='%s';",msg->name);
    if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg))
    {
        fprintf(stderr, "adminfind--sqlite3 get table: %s\n", errmsg);
        exit(-1);
    }
    if(nrow == 0){
        send(connfd,"N",2,0);
        return;
    }
    else if(nrow > 0)
    {
        send(connfd,"Y",2,0);
        int i, j;
        int count = 0;
        recv(connfd,buf,sizeof(buf),0);
        for (i = 0; i < nrow+1; i++) 
        {
            bzero(buf,sizeof(buf));
            for(j = 0;j < ncolumn;j++)
            {
                if(i == 0 && j < ncolumn)
                {
                    count++;
                    continue;  
                }
                sprintf(buf,"%-5s",resultp[count++]);
                printf(buf,"%-5s",resultp[count]);
            }
            ret = send(connfd,buf,sizeof(buf),0);
            if(ret < 0){
                perror("admin");
                break;
            }
        }
        bzero(buf,sizeof(buf));
        sprintf(buf,"over");
        send(connfd,buf,strlen(buf),0);
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    return;
}

void do_update()
{
    
    /*if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }*/
}

void do_repasswod(int connfd)
{
    int ret;
    int nrow = 0,ncolumn;
    char buf[100] = {0};
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    while(1)
    {
        bzero(buf,sizeof(buf));
        if(nrow > 0){
            ret = recv(connfd,msg,sizeof(*msg),0);
            if(ret < 0){
                perror("pwd.du");
                break;
            }
        }
        msg->name[strlen(msg->name)-1] = '\0';
        while(msg->name[strlen(msg->name)-1] ==' '){
            msg->name[strlen(msg->name)-1] = '\0';
        }
        sprintf(buf,"select * from passwod where user ='%s';",msg->name);
        char **resultp = NULL;
        if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
        {
            fprintf(stderr, "sqlite3 get table: %s\n", errmsg);
            break;
        }else if(nrow == 0){
            send(connfd,"C",2,0);
            continue;
        }
        else if(nrow > 0){
            bzero(buf,sizeof(buf));
            msg->pwd[strlen(msg->pwd)-1] = '\0';
            while(msg->pwd[strlen(msg->pwd)-1] ==' '){
            msg->pwd[strlen(msg->pwd)-1] = '\0';
            }
        }
        sprintf(buf,"update passwod set pwd='%s' where user='%s';",msg->pwd,msg->name);
        if (0 != sqlite3_exec(db,buf, NULL, NULL, &errmsg)) 
        {
            fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
            return;
        }
        send(connfd,"Y",2,0);
        break;
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
        return;
}

void do_adduser(int connfd)
{
    if(t == 0){
        send(connfd,"N",2,0);
        return;
    }
    int ret;
    int nrow = 0,ncolumn;
    char buf[100] = {0};
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    while(1)
    {
        bzero(buf,sizeof(buf));

        if(nrow > 0){
            ret = recv(connfd,msg,sizeof(*msg),0);
            if(ret < 0){
                perror("msg.du");
                break;
            }
        }
        msg->name[strlen(msg->name)-1] = '\0';
        while(msg->name[strlen(msg->name)-1] ==' '){
            msg->name[strlen(msg->name)-1] = '\0';
        }
        sprintf(buf,"select * from passwod where user ='%s';",msg->name);
        char **resultp = NULL;
        if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
        {
            fprintf(stderr, "sqlite3 get table: %s\n", errmsg);
            break;
        }else if(nrow > 0){
            send(connfd,"C",2,0);
            continue;
        }
        else if(nrow == 0){
            bzero(buf,sizeof(buf));
            msg->pwd[strlen(msg->pwd)-1] = '\0';
            sprintf(buf,"insert into passwod (user,pwd,flag) values('%s','%s','0');",msg->name,msg->pwd);
            if (0 != sqlite3_exec(db,buf, NULL, NULL, &errmsg)) 
            {
                fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
                return;
            }
            bzero(buf,sizeof(buf));
            sprintf(buf,"insert into informan (name) values ('%s');",msg->name);
            if (0 != sqlite3_exec(db,buf, NULL, NULL, &errmsg)) 
            {
                fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
                return;
            }
            send(connfd,"Y",2,0);
            break;
        }
    }
    ret = send(connfd,msg,sizeof(*msg),0);
    if(ret < 0){
        perror("数据异常");
        exit(-1);
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    return;
}

void do_delete(int connfd)
{
    if(t == 0){
        send(connfd,"N",2,0);
        return;
    }
    int ret;
    sqlite3 *db = NULL;
    char *errmsg = NULL;
    if (0 != sqlite3_open("infor.db", &db)) 
    {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(db));
        return;
    }
    char buf[100] = {0};
    int nrow= 1,ncolumn;
    msg->name[strlen(msg->name)-1] = '\0';

    while(1)
    {
        bzero(buf,sizeof(buf));
        if(nrow == 0){
        ret = recv(connfd,msg,sizeof(*msg),0);
            if(ret < 0){
                perror("delete.du");
                break;
            }
            msg->name[strlen(msg->name)-1] = '\0';
        }
        while(msg->name[strlen(msg->name)-1] == ' '){
            msg->name[strlen(msg->name)-1] = '\0';
        }
        sprintf(buf,"select * from passwod where user='%s';",msg->name);
        printf("%s\n",msg->name);
        char **resultp = NULL;
        if (0 != sqlite3_get_table(db,buf, &resultp, &nrow, &ncolumn, &errmsg)) 
        {
            fprintf(stderr, "sqlite3 get table: %s\n", errmsg);
            break;
        }else if(nrow == 0){
            send(connfd,"C",2,0);
            continue;
        }
        else if(nrow > 0)
        {
            bzero(buf,sizeof(buf));
            sprintf(buf,"delete from passwod where user='%s';",msg->name);
            if (0 != sqlite3_exec(db,buf, NULL, NULL, &errmsg)) 
            {
                fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
                break;
            }
            bzero(buf,sizeof(buf));
            sprintf(buf,"delete from informan where name='%s';",msg->name);
            if (0 != sqlite3_exec(db,buf, NULL, NULL, &errmsg)) 
            {
                fprintf(stderr, "sqlite3_exec: %s\n", errmsg);
                return;
            }
            send(connfd,"Y",2,0);
            break;
        }
    }
    if (0 != sqlite3_close(db))
    {
        fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db));
        exit(-1);
    }
    return;
}

int main()
{
    int sockfd;
    int man;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
    {
        perror("socket");
        exit(-1);
    }
    int on = 1;
    if(0 > setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))
    {
        perror("setsockopt");
        return(-1);
    }
    struct sockaddr_in servaddr;
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8888);
    servaddr.sin_addr.s_addr = inet_addr("192.168.0.122");
    
    if(0 > bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)))
    {
        perror("bind");
        exit(-1);
    }
    printf("bind is ok\n");
    int listenfd;
    if( 0 > listen(sockfd,BACK))
    {
        perror("listen");
        exit(-1);
    }
    printf("listen is ok\n");
    signal(SIGCHLD,handler);

    struct sockaddr_in cliaddr;
    int addrlen = sizeof(cliaddr);
    int connfd;
    while(1)
    {
        connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&addrlen);
        if(connfd < 0)
        {
            perror("accept");
            break;
        }
        printf("accept is ok\n");
        do_clean();
        printf("recv: %s input\n",inet_ntoa(cliaddr.sin_addr));
        pid_t pid;
        if(0 > (pid = fork()))
        {
            perror("fork");
            break;
        }
        else if(pid == 0)
        {
            close(listenfd);
            int ret;
            while(1)
            {
                bzero(msg->infor,sizeof(msg->infor));
                ret = recv(connfd,msg,sizeof(*msg),0);

                if(ret < 0)
                {
                    perror("recv");
                    printf("recv1: %s output\n",inet_ntoa(cliaddr.sin_addr));
                    break;
                }
                else if(ret == 0)
                {
                    printf("recv1: %s output\n",inet_ntoa(cliaddr.sin_addr));
                    do_clean();
                    break;
                }
                if(strncmp(msg->infor,"register",8) == 0)
                do_register(connfd);
                else if(strncmp(msg->infor,"find",4) == 0)
                do_find(connfd);
                else if(strncmp(msg->infor,"update",6) == 0)
                do_update(connfd);
                else if(strncmp(msg->infor,"repasswod",9) == 0)
                do_repasswod(connfd);
                else if(strncmp(msg->infor,"adduser",7) == 0)
                do_adduser(connfd);
                else if(strncmp(msg->infor,"delete",6) == 0)
                do_delete(connfd);
                else
                continue;
            }
            close(connfd);
            exit(0);
        }
    }
    return 0;
}

